package com.smart.thrift.config.client;


import com.smart.thrift.base.DefaultSerializer;
import com.smart.thrift.base.ThriftSerializer;
import com.smart.thrift.discoveryandbalance.discovery.AbstractRegistry;
import com.smart.thrift.discoveryandbalance.discovery.Registry;
import com.smart.thrift.model.common.ThriftClientProperties;
import com.smart.thrift.model.pool.TransportKeyedObjectPool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
import org.apache.thrift.transport.TTransport;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

import java.security.NoSuchAlgorithmException;


@Slf4j
@EnableConfigurationProperties(ThriftClientProperties.class)
public class ThriftClientAutoConfiguration {

    @Bean
    public GenericKeyedObjectPoolConfig<TTransport> keyedObjectPoolConfig(ThriftClientProperties properties) {
        ThriftClientProperties.ThriftClientPoolProperties poolProperties = properties.getPool();
        GenericKeyedObjectPoolConfig<TTransport> config = new GenericKeyedObjectPoolConfig<>();
        config.setMinIdlePerKey(poolProperties.getPoolMinIdlePerKey());
        config.setMaxIdlePerKey(poolProperties.getPoolMaxIdlePerKey());
        config.setMaxWaitMillis(poolProperties.getPoolMaxWait());
        config.setMaxTotalPerKey(poolProperties.getPoolMaxTotalPerKey());
        config.setTestOnCreate(poolProperties.isTestOnCreate());
        config.setTestOnBorrow(poolProperties.isTestOnBorrow());
        config.setTestOnReturn(poolProperties.isTestOnReturn());
        config.setTestWhileIdle(poolProperties.isTestWhileIdle());
        config.setFairness(true);
        config.setJmxEnabled(false);
        return config;
    }

    @Bean
    @ConditionalOnMissingBean
    public TransportKeyedObjectPool transportKeyedObjectPool(GenericKeyedObjectPoolConfig<TTransport> config,
                                                             ThriftClientProperties properties) {
        return new TransportKeyedObjectPool(new TransportKeyedObjectPool.TransportKeyedPooledObjectFactory(properties), config);
    }

    @Bean
    @ConditionalOnMissingBean
    public ThriftSerializer defaultThriftSerializer() {
        return new DefaultSerializer();
    }

    @Bean
    @ConditionalOnMissingBean
    public ThriftClientManager thriftClientManager(ThriftClientProperties properties,
                                                   TransportKeyedObjectPool objectPool) throws NoSuchAlgorithmException {
        ThriftClientManager instance = ThriftClientManager.getInstance();
        instance.setProperties(properties);
        instance.setObjectPool(objectPool);
        ThriftClientProperties.ThriftClientDiscoveryProperties discovery = properties.getDiscovery();
        Registry.RegistryProperties registryProperties = new Registry.RegistryProperties();
        registryProperties.setDiscoveryType(discovery.getType());
        registryProperties.setHost(discovery.getHost());
        registryProperties.setPort(discovery.getPort());
        //如果连接registry使用baseAuth，可使用BaseAuthProperties， SSLContext
        instance.setRegistry(AbstractRegistry.getInstance(registryProperties));
        return instance;
    }
}
